/**
 * Paginator Jsp a Utility for pagination record 
 * from jpa Entity list Databases
 * 
 * @author Federico Colantoni, Diego Falcinelli
 * Version 0.8.0
 */
package multiface.web.util;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import multiface.valentinorusso.jpa.Opzioni;
import multiface.valentinorusso.jpa.util.PersistenceManager;

public class Paginator {

    private int currentIndex;
    private int totalElements;
    private int elementsForPage;
    private int maxPage;
    private String pageReturn;
    private String functionJS;
    private String CSSClassPage;
    private String CSSClassCurrentPage;
    private String CSSClass;
    private Map<String, String> parameters;
    private String spacer = " - ";

    public Paginator() {
        this.parameters = new HashMap<String, String>();
    }

    public void setElementsForPage_fromDB(boolean admin) {
        EntityManagerFactory emf = PersistenceManager.getInstance().getEntityManagerFactory();
        EntityManager em = emf.createEntityManager();

        Opzioni op = em.createNamedQuery("Opzioni.findAll", Opzioni.class).getSingleResult();
        em.refresh(op);

        int max = op.getMaxRecordPag();
        if (admin) {
            max = op.getMaxRecordPagAdmin();
        }

        maxPage = 10;//op.getMaxPagPaginator();

        em.close();

        elementsForPage = max;

    }

    public void addParameter(String key, String value) {
        ////Sy_stem.out.println(key+":"+value);
        this.parameters.put(key, value);
    }

    public void removeParameter(String key) {
        this.parameters.remove(key);
    }

    /**
     * @return the currentIndex
     */
    public int getCurrentIndex() {
        return currentIndex;
    }

    /**
     * @param currentIndex the currentIndex to set
     */
    public void setCurrentIndex(int currentIndex) {
        this.currentIndex = currentIndex;
    }

    /**
     * @return the totalElements
     */
    public int getTotalElements() {
        return totalElements;
    }

    /**
     * @param totalElements the totalElements to set
     */
    public void setTotalElements(int totalElements) {
        this.totalElements = totalElements;
    }

    /**
     * @return the elementsForPage
     */
    public int getElementsForPage() {
        return elementsForPage;
    }

    /**
     * @param elementsForPage the elementsForPage to set
     */
    public void setElementsForPage(int elementsForPage) {
        this.elementsForPage = elementsForPage;
    }

    /**
     * @return the pageReturn
     */
    public String getPageReturn() {
        return pageReturn;
    }

    /**
     * @param pageReturn the pageReturn to set
     */
    public void setPageReturn(String pageReturn) {
        this.pageReturn = pageReturn;
    }

    /**
     * @return the functionJS
     */
    public String getFunctionJS() {
        return functionJS;
    }

    /**
     * @param functionJS the functionJS to set
     */
    public void setFunctionJS(String functionJS) {
        this.functionJS = functionJS;
    }

    @Override
    public String toString() {
        String res = "";
        if (CSSClass == null) {
            res += "<div>";
        } else {
            res += "<div class=\"" + CSSClass + "\">";
        }
        String currentCSS = "";
        if (CSSClassCurrentPage != null) {
            currentCSS = "class=\"" + CSSClassCurrentPage + "\"";
        }
        String normalCSS = "";
        if (CSSClassPage != null) {
            normalCSS = "class=\"" + CSSClassPage + "\"";
        }

        int _totalPage = (totalElements / elementsForPage) + 1;
        int _sectionsPage = _totalPage / maxPage;

        
        int _startPage = (currentIndex/(elementsForPage*maxPage))*maxPage;
        int _stopPage = _startPage + maxPage;
        
         if (_stopPage > _totalPage) {
             _stopPage = _totalPage;
         }

        if (_startPage > 0) {
            // Inserisco il prev
            res += "<a " + normalCSS + " href=\"";
            if (functionJS == null) {
                res += pageReturn + parametersToGet("index", ((Integer) ((_startPage-1) * elementsForPage)).toString());
            } else {
                res += "javascript:" + functionJS + "('" + pageReturn + "'," + parametersToJSON("index", ((Integer) ((_startPage-1) * elementsForPage)).toString()) + ")";
            }
            res += "\"><</a> ";
        }

        for (int i = _startPage; i < _stopPage; i++) {
            if ((i * elementsForPage) == currentIndex) {
                res += "<a " + currentCSS + " href=\"";
            } else {
                res += "<a " + normalCSS + " href=\"";
            }
            if (functionJS == null) {
                res += pageReturn + parametersToGet("index", ((Integer) (i * elementsForPage)).toString());
            } else {
                res += "javascript:" + functionJS + "('" + pageReturn + "'," + parametersToJSON("index", ((Integer) (i * elementsForPage)).toString()) + ")";
            }
            res += "\">" + (i + 1) + "</a>";
            if (i < _stopPage - 1) {
                res += spacer;
            }
        }

        if (_totalPage > _stopPage) {
            // Inserisco il next
            res += " <a " + normalCSS + " href=\"";
            if (functionJS == null) {
                res += pageReturn + parametersToGet("index", ((Integer) (_stopPage * elementsForPage)).toString());
            } else {
                res += "javascript:" + functionJS + "('" + pageReturn + "'," + parametersToJSON("index", ((Integer) (_stopPage * elementsForPage)).toString()) + ")";
            }
            res += "\">></a>";
        }
        res += "</div>";
        return res;
    }

    /**
     * @return the CSSClassPage
     */
    public String getCSSClassPage() {
        return CSSClassPage;
    }

    /**
     * @param CSSClassPage the CSSClassPage to set
     */
    public void setCSSClassPage(String CSSClassPage) {
        this.CSSClassPage = CSSClassPage;
    }

    /**
     * @return the CSSClassCurrentPage
     */
    public String getCSSClassCurrentPage() {
        return CSSClassCurrentPage;
    }

    /**
     * @param CSSClassCurrentPage the CSSClassCurrentPage to set
     */
    public void setCSSClassCurrentPage(String CSSClassCurrentPage) {
        this.CSSClassCurrentPage = CSSClassCurrentPage;
    }

    /**
     * Funzioni private
     */
    private String parametersToGet() {
        String res = "?";
        Set<String> keys = parameters.keySet();
        Iterator<String> it = keys.iterator();
        while (it.hasNext()) {
            String k = it.next();
            String v = parameters.get(k);
            res += k + "=" + v;
            if (it.hasNext() == true) {
                res += "&";
            }
        }
        return res;
    }

    private String parametersToGet(String key, String value) {
        String res = "?";

        Map<String, String> parametersClone = cloneParameters();
        parametersClone.put(key, value);

        Set<String> keys = parametersClone.keySet();
        Iterator<String> it = keys.iterator();
        while (it.hasNext()) {
            String k = it.next();
            String v = parametersClone.get(k);
            res += k + "=" + v;
            if (it.hasNext() == true) {
                res += "&";
            }
        }
        return res;
    }

    private String parametersToJSON() {
        String res = "{";
        Set<String> keys = parameters.keySet();
        Iterator<String> it = keys.iterator();
        while (it.hasNext()) {
            String k = it.next();
            String v = parameters.get(k);
            res += k + ":" + "'" + v + "'";
            if (it.hasNext() == true) {
                res += ",";
            }
        }
        return res + "}";
    }

    private String parametersToJSON(String key, String value) {
        String res = "{";

        Map<String, String> parametersClone = cloneParameters();
        parametersClone.put(key, value);

        Set<String> keys = parametersClone.keySet();
        Iterator<String> it = keys.iterator();
        while (it.hasNext()) {
            String k = it.next();
            String v = parametersClone.get(k);
            res += k + ":" + "'" + v + "'";
            if (it.hasNext() == true) {
                res += ",";
            }
        }
        return res + "}";
    }

    /**
     * @return the CSSClass
     */
    public String getCSSClass() {
        return CSSClass;
    }

    /**
     * @param CSSClass the CSSClass to set
     */
    public void setCSSClass(String CSSClass) {
        this.CSSClass = CSSClass;
    }

    //<a href=\"javascript:this.functionJS('" + pageReturn + "',{parametersClone})\">text</a>
    public String getFunction(String key, String value, String text) {
        return "<a href=\"javascript:" + functionJS + "('" + pageReturn + "'," + parametersToJSON(key, value) + ");\">" + text + "</a>";
    }

    //<a href=\"javascript:newfunctionJS('" + pageReturn + "',{parametersClone})\">text</a>
    public String getFunction(String newFunctionJS, String key, String value, String text) {
        return "<a href=\"javascript:" + newFunctionJS + "('" + pageReturn + "'," + parametersToJSON(key, value) + ");\">" + text + "</a>";
    }

    //<a href=\"javascript:newfunctionJS('" + newpageReturn + "',{parametersClone})\">text</a>
    public String getFunction(String newFunctionJS, String newPageReturn, String key, String value, String text) {
        return "<a href=\"javascript:" + newFunctionJS + "('" + newPageReturn + "'," + parametersToJSON(key, value) + ");\">" + text + "</a>";
    }

    private Map<String, String> cloneParameters() {
        Map<String, String> parametersClone = new HashMap<String, String>();

        Set<String> keys = parameters.keySet();
        Iterator<String> it = keys.iterator();
        while (it.hasNext()) {
            String k = it.next();
            String v = parameters.get(k);
            parametersClone.put(k, v);
        }

        return parametersClone;

    }
}
